package com.mspbots.rule.queue.timeentry;

import com.mspbots.cw.request.TenantRuleDTO;
import com.mspbots.cw.request.TenantTimeEntryDTO;
import com.mspbots.rule.exceptions.BaseRule;
import lombok.extern.slf4j.Slf4j;
import org.jeasy.rules.api.Facts;
import org.jeasy.rules.api.Rules;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.lang.reflect.InvocationTargetException;
import java.util.Map;

import static com.mspbots.rule.config.RuleConfiguration.REDIS_KEY_PREFIX_TENANT;

/**
 * @ClassName com.mspbots.rule.queue.timeentry.IncludingWordsQueue
 * @Description TODO
 * @Author Jun
 * @Date 2019/8/30 19:27
 * @Version 1.0
 **/
@Slf4j
@Component
public class IncludingPasswordQueue extends TimeEntryBaseQueue {

    private static final String RULE_NAME = "IncludingPassword";
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @RabbitListener(queues = "trigger.timeEntry.IncludingPassword")
    public void onQueue(TenantTimeEntryDTO tenantTimeEntryDTO) {
//        super.onRule(RULE_NAME,tenantTimeEntryDTO);
        onRule(RULE_NAME, tenantTimeEntryDTO);
    }


    protected Mono<TenantRuleDTO> check(String ruleName, Long tenantId) {
        Map<String, Object> ruleParams = Map.of("tenantId", tenantId, "enable", true, "name", ruleName);
        return this.coreClient.get("/tenant/rule/detail", ruleParams, TenantRuleDTO.class)
                .switchIfEmpty(Mono.error(new TenantRuleNotFoundException("TenantRuleDTO get is null.")))
                .filter(dto -> {
                    String enable = this.stringRedisTemplate.opsForValue()
                            .get(REDIS_KEY_PREFIX_TENANT + tenantId + ":" + dto.getRuleId() + "_enable");
                    return Boolean.parseBoolean(enable);
                })
                .switchIfEmpty(Mono.error(new TenantRuleNotFoundException("this Tenant Rule is not enable.")));

    }

    protected void onRule(String ruleName, Long tenantId) {
        check(ruleName, tenantId)
                .map(ruleDto -> {
                    try {
                        Class clz = Class.forName(ruleDto.getClassName());
                        return clz.getDeclaredConstructor().newInstance();
                    } catch (ClassNotFoundException | InstantiationException
                            | InvocationTargetException | NoSuchMethodException
                            | IllegalAccessException e) {
                        return e;
                    }
                })
                .map(c -> (BaseRule) c)
                .subscribe(instance -> {
                    Rules rules = new Rules();
                    instance.init(tenantRuleDTO, messageProducer, messagesService, tenantUserMappingService,
                            tenantConfigurationService, coreClient, objectMapper);
                    instance.setStringRedisTemplate(stringRedisTemplate);
                    rules.register(instance);
                    Facts facts = new Facts();
                    facts.put(BaseRule.FACT, tenantId);
                    rulesEngine.fire(rules, facts);
                }, err -> log.error("onRule is error {}", err.getMessage()));
    }


}
